package util

import (
	"net/http"
	"strings"

	"github.com/gin-gonic/gin"
	"github.com/gin-gonic/gin/binding"
	"github.com/go-playground/locales/en"
	"github.com/go-playground/locales/zh"
	ut "github.com/go-playground/universal-translator"
	"github.com/go-playground/validator/v10"
	zht "github.com/go-playground/validator/v10/translations/zh"
)

type errorCode int

const (
	Success            errorCode = 200
	Failed             errorCode = 500
	ParamError         errorCode = 400
	NotFound           errorCode = 404
	UnAuthorized       errorCode = 401
	CaptchaFailed      errorCode = 501
	RedisFailed        errorCode = 502
	VerificationFailed errorCode = 503
)

var codeMsg = map[errorCode]string{
	Success:            "成功",
	Failed:             "系统异常",
	ParamError:         "参数错误",
	NotFound:           "记录不存在",
	UnAuthorized:       "未授权",
	CaptchaFailed:      "验证码生成失败",
	RedisFailed:        "缓存失败或失效",
	VerificationFailed: "验证失败",
}

var trans ut.Translator

// 注册validator中文翻译
func init() {
	uni := ut.New(en.New(), zh.New())
	trans, _ = uni.GetTranslator("zh")
	validate := binding.Validator.Engine().(*validator.Validate)
	_ = zht.RegisterDefaultTranslations(validate, trans)
}

func Translate(err error) string {
	errors, ok := err.(validator.ValidationErrors)
	if !ok {
		return err.Error()
	}
	result := make([]string, 0)
	for _, err := range errors {
		errMsg := err.Translate(trans)
		if errMsg == "" {
			continue
		}
		result = append(result, errMsg)
	}
	return strings.Join(result, ",")
}

func RespSuccess(ctx *gin.Context, msg string, data interface{}) {
	ctx.JSON(http.StatusOK, gin.H{
		"code":     Success,
		"message":  msg,
		"data":     data,
		"trace_id": ctx.GetString("trace_id"),
	})
}

func RespFailed(ctx *gin.Context, code errorCode, msg string) {
	errMsg := codeMsg[code] + ": " + msg
	ctx.AbortWithStatusJSON(http.StatusOK, gin.H{
		"code":     code,
		"message":  errMsg,
		"data":     nil,
		"trace_id": ctx.GetString("trace_id"),
	})
	if code != Success {
		ctx.Set("error_code", int(code))
		ctx.Set("error_msg", msg)
	}
}

func RespNotFound(ctx *gin.Context, msg string) {
	ctx.JSON(http.StatusNotFound, gin.H{
		"code":     http.StatusNotFound,
		"message":  msg,
		"data":     nil,
		"trace_id": ctx.GetString("trace_id"),
	})
}

func RespRedirect(ctx *gin.Context, url string) {
	ctx.Redirect(http.StatusFound, url)
}
